﻿using System;
using System.Collections.Generic;
using System.Collections;

namespace eWallet.Collections.Generic
{
	public class EventfulList<T> : IList<T>
	{

		public EventfulList() { }

		public EventfulList(params T[] items)
		{
			if (null != items)
			{
				this.InnerList.AddRange(items);
			}
		}

		private List<T> InnerList = new List<T>();



		private EventHandler<ListItemEventArgs<T>> AddedHandler;
		public event EventHandler<ListItemEventArgs<T>> Added
		{
			add { this.AddedHandler += value; }
			remove { this.AddedHandler -= value; }
		}

		private EventHandler ClearedHandler;
		public event EventHandler Cleared
		{
			add { this.ClearedHandler += value; }
			remove { this.ClearedHandler -= value; }
		}

		private EventHandler<ListItemEventArgs<T>> RemovedHandler;
		public event EventHandler<ListItemEventArgs<T>> Removed
		{
			add { this.RemovedHandler += value; }
			remove { this.RemovedHandler -= value; }
		}



		public T this[int index]
		{
			get { return this.InnerList[index]; }
			set { this.InnerList[index] = value; }
		}

		public int Count
		{
			get { return this.InnerList.Count; }
		}

		public bool IsReadOnly
		{
			get { return ((ICollection<T>)this.InnerList).IsReadOnly; }
		}



		public void Add(T item)
		{
			this.InnerList.Add(item);
			this.OnAdded(new ListItemEventArgs<T>(item, this.Count - 1));
		}

		public void Clear()
		{
			if (this.InnerList.Count > 0)
			{
				this.InnerList.Clear();
				this.OnCleared(EventArgs.Empty);
			}
		}

		public bool Contains(T item)
		{
			return this.InnerList.Contains(item);
		}

		public void CopyTo(T[] array, int arrayIndex)
		{
			this.InnerList.CopyTo(array, arrayIndex);
		}

		public IEnumerator<T> GetEnumerator()
		{
			return this.InnerList.GetEnumerator();
		}

		IEnumerator IEnumerable.GetEnumerator()
		{
			return ((IEnumerable)this.InnerList).GetEnumerator();
		}

		public int IndexOf(T item)
		{
			return this.InnerList.IndexOf(item);
		}

		public void Insert(int index, T item)
		{
			this.InnerList.Insert(index, item);
			this.OnAdded(new ListItemEventArgs<T>(item, index));
		}

		public bool Remove(T item)
		{
			int index = -1;
			if (this.Contains(item))
			{
				index = this.IndexOf(item);
			}

			bool b = this.InnerList.Remove(item);
			if (b)
			{
				this.OnRemoved(new ListItemEventArgs<T>(item, index));
			}
			return b;
		}

		public void RemoveAt(int index)
		{
			var item = this[index];
			this.InnerList.RemoveAt(index);
			this.OnRemoved(new ListItemEventArgs<T>(item, index));
		}



		protected virtual void OnAdded(ListItemEventArgs<T> e)
		{
			if (null != this.AddedHandler)
			{
				this.AddedHandler(this, e);
			}
		}

		protected virtual void OnCleared(EventArgs e)
		{
			if (null != this.ClearedHandler)
			{
				this.ClearedHandler(this, e);
			}
		}

		protected virtual void OnRemoved(ListItemEventArgs<T> e)
		{
			if (null != this.RemovedHandler)
			{
				this.RemovedHandler(this, e);
			}
		}

	}
	
}
